/**
 * 
 */
package any.tag.gwt.client.ui;

import any.gwt.client.http.AsynClientEvent;
import any.gwt.client.http.AsynClientListener;
import any.gwt.client.ui.Span;
import any.gwt.client.util.DispacherContainer;
import any.gwt.client.util.DispatchEvent;
import any.gwt.client.util.DispatcherListener;

import com.allen_sauer.gwt.log.client.Log;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONParser;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Widget;

/**
 * TODO: Doc me
 * 
 * @author keke <keke@codehaus.org>
 * @version 0.0.1
 * @revision $Revision:$
 */
public class TagBar extends Composite implements AsynClientListener,
        ClickListener, DispatcherListener {
    private final String    itemURI;
    private boolean         loaded = true;
    private final FlowPanel outer;
//    private final TagClient tagClient;
    private JSONArray       tags;

    public TagBar(final String itemURI) {
        this(itemURI, null);
        loaded = false;
    }

    public TagBar(final String itemURI, final JSONArray tags) {
        super();
        DispacherContainer.getGlobalDispatcher().addDispatcherListener(this);
        this.itemURI = itemURI;
        this.tags = tags;
//        this.tagClient = tagClient;
        outer = new FlowPanel();
        final Span tagLabel = new Span("Tags:");
        outer.add(tagLabel);
        tagLabel.addStyleName("editor");
        tagLabel.addClickListener(this);
        initWidget(outer);
        setStyleName("tagbar");
        addStyleName("link");
    }

    public void fireDispatchEvent(final DispatchEvent event) {
        if (event.isConsumed()) {
            return;
        }
        if (event.getName().equals("tagItemsLoaded")) {
            final Object[] content = (Object[]) event.getContent();
            if (content[0].equals(itemURI)) {
                if (Log.isDebugEnabled()) {
                    Log.debug("Loading tags");
                }
                tags = (JSONArray) content[1];
                updateTags();
                loaded = true;
                event.consume();
            }
        } else if (event.getName().equals("tagsSaved")) {
            final Object[] content = (Object[]) event.getContent();
            if (content[0].equals(itemURI)) {
                setTags((JSONArray) content[1]);
            }
        }
    }

    public void fireEvent(final AsynClientEvent event) {
        if (event.getName().equals("tagsOfURI")) {
            tags = JSONParser.parse(event.getResponse().getText()).isArray();
            updateTags();
            loaded = true;
        }

    }

    public void onClick(final Widget sender) {
        if (Log.isDebugEnabled()) {
            Log.debug(sender + " was clicked");
        }
        final TagEditDialog tagEditor = new TagEditDialog(itemURI,
                getTagString());
        tagEditor.center();
    }

    public void setTags(final JSONArray tags) {
        this.tags = tags;
        updateTags();
    }

    private void clearTags() {
        while (outer.getWidgetCount() > 1) {
            outer.remove(1);
        }
    }

    private String getTagString() {
        if (tags == null || tags.size() == 0) {
            return "";
        }
        final StringBuffer sb = new StringBuffer();
        for (int i = 0; i < tags.size(); i++) {
            if (i != 0) {
                sb.append(", ");
            }
            sb.append(tags.get(i).isObject().get("tag").isObject().get("name")
                    .isString().stringValue());
        }
        return sb.toString();
    }

    private void updateTags() {
        if (tags == null) {
            return;
        }
        clearTags();
        for (int i = 0; i < tags.size(); i++) {
            final JSONObject tag = tags.get(i).isObject();
            final TagLink tagSpan = new TagLink(tag.get("tag").isObject().get(
                    "name").isString().stringValue());
            outer.add(tagSpan);
        }
    }

    protected void onLoad() {
        if (!loaded) {
            DispacherContainer.getGlobalDispatcher().dispatch(
                    new DispatchEvent(this, itemURI, "loadingTagBar"));
            // tagClient.getTagsOfURI(itemURI, this);
        } else {
            updateTags();
        }
    }

    protected void onUnload() {
        DispacherContainer.getGlobalDispatcher().removeDispatcherListener(this);
    }

}
